﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using Physics;
using System.Windows.Media.Media3D;

namespace CasinoProject
{
    /// <summary>
    /// Prosty delegat do funkcji bez argumentów
    /// </summary>
    public delegate void SimpleEvent();

    
    /// <summary>
    /// Kontrolka do wyświetlania animacji kości
    /// </summary>
	public partial class DiceViewControl
	{
        DiceSimulation diceSimulation;

        Transform3D dice0InitialTransform;
        Transform3D dice1InitialTransform;
        Vector3D oldDirection = new Vector3D();

        int frameNumber = 0;

        /// <summary>
        /// Obiekt odpowiedzialny za symulowanie ruchu kości
        /// </summary>
        public DiceSimulation DiceSimulation
        {
            get { return diceSimulation; }
        }

        /// <summary>
        /// konstruktor
        /// </summary>
		public DiceViewControl()
		{
			this.InitializeComponent();

            diceSimulation = new DiceSimulation();
            diceSimulation.PhysicsSimulator.Paused = true;
			// Insert code required on object creation below this point.

            //CompositionTarget

            dice0InitialTransform = Dice1.Transform;
            dice1InitialTransform = Dice2.Transform;

		}
        public bool SimulationInProgress
        {
            get
            {
                return !diceSimulation.PhysicsSimulator.Paused;
            }
        }

        /// <summary>
        /// Resetuje parametry kontrolki
        /// </summary>
        public void ResetView()
        {
            Dice1.Transform = dice0InitialTransform;
            Dice2.Transform = dice1InitialTransform;
            frameNumber = 0;

            aimLabel.Content = "Aim:";
            aimLabel.Visibility = Visibility.Hidden;

            scoreLabel.Content = "Score";
            scoreLabel.Visibility = Visibility.Hidden;

            Camera1.Position = new Point3D(0, 0, 60);
            //Camera1.LookDirection = oldDirection;
        }

        /// <summary>
        /// Ustawia cel gracza (liczba jaką próbuje wyrzucić)
        /// </summary>
        /// <param name="aim"></param>
        public void SetAim(int aim)
        {
            if (aim>1)
            {
                aimLabel.Content = "Aim: " + aim.ToString();
                aimLabel.Visibility = Visibility.Visible;
            }
            else
            {
                aimLabel.Visibility = Visibility.Hidden;
            }
        }

        /// <summary>
        /// Zaczyna animację kości
        /// </summary>
        /// <param name="direction">Kierunek rzutu</param>
        /// <param name="velocity">Prędkość początkowa kości</param>
        public void StartAnimation(MyMath.MyVector direction, double velocity)
        {
            ResetView();
            MyMath.MyVector vec = direction;
            vec.Normalize();


            diceSimulation.StartSimulation(vec, (float)velocity);
        }

        /// <summary>
        /// Pokazuje wynik
        /// </summary>
        void ShowScore()
        {

            scoreLabel.Content = "Score:" + (diceSimulation.Result.dice1 + diceSimulation.Result.dice2).ToString();
            scoreLabel.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Uaktualnia symulację
        /// </summary>
        /// <param name="timeElapsed">Czas jaki upłynął od ostatniego uaktualnienia</param>
        public void UpdateSimulation(double timeElapsed)
        {
            if (!diceSimulation.PhysicsSimulator.Paused)
            {
                diceSimulation.UpdateSimulation((float)timeElapsed);

                frameNumber++;
                //frameCounterLabel.Content = frameNumber.ToString();
                if (SimulationStopped!=null && diceSimulation.PhysicsSimulator.Paused)
                {
                    SimulationStopped();

                    ShowScore();
                    return;

                }
                MyMath.MyVector pos0 = diceSimulation.Dices[0].Position;
                MyMath.MyVector pos1 = diceSimulation.Dices[1].Position;

                MyMath.MyQuaternion ori0 = diceSimulation.Dices[0].Orientation;
                MyMath.MyQuaternion ori1 = diceSimulation.Dices[1].Orientation;

                Transform3DGroup transform0 = new Transform3DGroup();                
                Quaternion q0 = new Quaternion(ori0.Vector.X, ori0.Vector.Y, ori0.Vector.Z, ori0.Scalar);
                transform0.Children.Add(new RotateTransform3D(new QuaternionRotation3D(q0)));
                transform0.Children.Add(new TranslateTransform3D(pos0.X, pos0.Y, pos0.Z));
                Dice1.Transform = transform0;

                Transform3DGroup transform1 = new Transform3DGroup();                
                Quaternion q1 = new Quaternion(ori1.Vector.X, ori1.Vector.Y, ori1.Vector.Z, ori1.Scalar);
                transform1.Children.Add(new RotateTransform3D(new QuaternionRotation3D(q1)));
                transform1.Children.Add(new TranslateTransform3D(pos1.X, pos1.Y, pos1.Z));
                Dice2.Transform = transform1;
            }
        }

        /// <summary>
        /// Zatrzymuje symulację
        /// </summary>
        public void StopSimulation()
        {
            diceSimulation.PhysicsSimulator.Paused = true;
        }

        /// <summary>
        /// Event informujący o końcu symulacji
        /// </summary>
        public event SimpleEvent SimulationStopped;

        public void BeginEndingAnimation()
        {
            oldDirection = Camera1.LookDirection;
            Vector3DAnimation anim_pos = new Vector3DAnimation(new Vector3D(0, 30, 60), new Duration(TimeSpan.FromSeconds(2)));
            MyMath.MyVector v = this.diceSimulation.Dices[0].Position + this.diceSimulation.Dices[1].Position;
            v /= 2;
            MyMath.MyVector dir = v - new MyMath.MyVector(0, 30, 60);
            dir.Normalize();
            Vector3DAnimation anim_dir = new Vector3DAnimation(new Vector3D(dir.X, dir.Y, dir.Z), new Duration(TimeSpan.FromSeconds(2)));

            MyMath.MyVector dir1 = new MyMath.MyVector(oldDirection.X, oldDirection.Y, oldDirection.Z);
            MyMath.MyVector normal = dir1 ^ dir;
            normal.Normalize();
            MyMath.MyQuaternion qrot = MyMath.MyQuaternion.FromAxisAngle((float)Math.Acos(dir * dir1), normal);
            Transform3DGroup group = new Transform3DGroup();
            group.Children.Add(new TranslateTransform3D(new Vector3D(0, 30, 0)));
            Quaternion q = new Quaternion(qrot.Vector.X, qrot.Vector.Y, qrot.Vector.Z, qrot.Scalar);

            group.Children.Add(new RotateTransform3D(new QuaternionRotation3D(q)));
                        
            //group.Children.Add(new RotateTransform3D(
            //Camera1.Transform.BeginAnimation()
        }

	}
}
